package chis.fx.stage;

import java.util.ArrayList;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;









import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BorderPaneStage extends Stage {

	///////////////////////////////////////////////////////////////

	// Constant data members.
	private final String stageTitle = "BorderPane Stage";
	private final double SCENE_WIDTH = 800;
	private final double SCENE_HEIGHT = 600;
	private final double SCENE_INSET_TOP = 10;
	private final double SCENE_INSET_RIGHT = 10;
	private final double SCENE_INSET_BOTTOM = 10;
	private final double SCENE_INSET_LEFT = 10;
	private final double HUD_WIDTH_PERCENT = 1;
	private final double HUD_HEIGHT_PERCENT = .30;
	private final double GAMECANVAS_WIDTH_PERCENT = 1;
	private final double GAMECANVAS_HEIGHT_PERCENT = .70;

	// Variable data members.

	// Layout dimensions.
	private double adjustedSceneWidth;
	private double adjustedSceneHeight;
	private double HUDWidth;
	private double HUDHeight;
	private double gameCanvasWidth;
	private double gameCanvasHeight;

	// Circle values.
	private double circleWidth;
	private double circleRadius;	
	private int numOfCirclesAcross;
	private int numOfCirclesDown;
	private int totalNumOfCircles;

	// Collection of clicked circle coordinates.
	private Map<Integer,MyPoint> clickedCircleCoordinates;

	private BorderPane root;
	private Scene scene;
	private FlowPane HUDPane;
	private FlowPane gameCanvasPane;

	private ArrayList<EventHandler<MouseEvent>> clickHandlerList;

	private int clickCount;

	public BorderPaneStage(int numberOfCirclesAcross) {
		numOfCirclesAcross = numberOfCirclesAcross;

		clickHandlerList = new ArrayList<EventHandler<MouseEvent>>();

		clickedCircleCoordinates = new TreeMap<Integer,MyPoint>();
		initialiseMyStage();
	}

	private void initialiseMyStage() {
		this.setResizable(false);
		this.setTitle(stageTitle);

		root = new BorderPane();
		Insets insets = new Insets(SCENE_INSET_TOP,SCENE_INSET_RIGHT,SCENE_INSET_BOTTOM,SCENE_INSET_LEFT);
		root.setPadding(insets);

		scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT, Color.PINK);

		layoutStage();	

		this.setScene(scene);
	}

	private void layoutStage() {
		adjustSceneDimensions();
		calculateHUDDimensions();
		calculateGameCanvasDimensions();
		makeHUD();
		makeGameCanvas();
		//testing();

		//endGame();
	}

	private void adjustSceneDimensions() {
		adjustedSceneWidth = SCENE_WIDTH - (SCENE_INSET_LEFT + SCENE_INSET_RIGHT);
		adjustedSceneHeight = SCENE_HEIGHT - (SCENE_INSET_TOP + SCENE_INSET_BOTTOM);
	}

	private void calculateHUDDimensions() {
		HUDWidth = HUD_WIDTH_PERCENT * adjustedSceneWidth;
		HUDHeight = HUD_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void calculateGameCanvasDimensions() {
		gameCanvasWidth = GAMECANVAS_WIDTH_PERCENT * adjustedSceneWidth;
		gameCanvasHeight = GAMECANVAS_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void makeHUD() {
		HUDPane = new FlowPane();
		HUDPane.setPrefSize(HUDWidth, HUDHeight);
		root.setTop(HUDPane);
	}

	private void makeGameCanvas() {
		gameCanvasPane = new FlowPane();
		gameCanvasPane.setPrefSize(gameCanvasWidth, gameCanvasHeight);
		initialiseCircleCollectionDimensions();

		for (int x = 0; x < totalNumOfCircles; x ++) {
			Circle c = new Circle(circleRadius, Color.web("white", 1));

			// Click handler.
			// Make.
			EventHandler<MouseEvent> mc = makeCircleClickHandler();
			// Add to circle.
			c.addEventHandler(MouseEvent.MOUSE_CLICKED, mc);
			// Add to list.
			this.clickHandlerList.add(mc);

			c.addEventHandler(MouseEvent.MOUSE_MOVED, makeCircleMovedHandler());
			c.addEventHandler(MouseEvent.MOUSE_ENTERED, makeCircleEnteredHandler());
			c.addEventHandler(MouseEvent.MOUSE_EXITED, makeCircleExitHandler());
			gameCanvasPane.getChildren().add(c);
		}

		root.setCenter(gameCanvasPane);

	}

	private EventHandler<MouseEvent> makeCircleClickHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				MyPoint p = new MyPoint(event.getSceneX(),event.getSceneY());
				addClickedCircle(p);
				removeClickHandlerFromCircle(p);
				incrementClickCount();
			}
		};
		return clickHandler;
	}

	private void removeClickHandlerFromCircle(MyPoint clickedInScene) {
		// Get the Circle's position.
		MyPoint p = findCircle(clickedInScene);
		// Use the circle's position to gte it's click handler from the list.
		EventHandler<MouseEvent> h = this.clickHandlerList.get(p.getPosition());
		// Get the circle from the game canvas.
		Circle c = (Circle)gameCanvasPane.getChildren().get(p.getPosition());
		// Remove the click handler.
		c.removeEventHandler(MouseEvent.MOUSE_CLICKED, h);
	}

	private void incrementClickCount() {
		clickCount ++;
		if(clickCount == this.totalNumOfCircles) {
			endGame();
		}
	}

	private EventHandler<MouseEvent> makeCircleMovedHandler(){
		EventHandler<MouseEvent> movedHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println(event.getSceneX());
				System.out.println(event.getSceneY());
			}
		};
		return movedHandler;
	}

	private EventHandler<MouseEvent> makeCircleEnteredHandler(){
		EventHandler<MouseEvent> enteredHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("Entered");
			}
		};
		return enteredHandler;
	}

	private EventHandler<MouseEvent> makeCircleExitHandler(){
		EventHandler<MouseEvent> exitHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("Exited");
			}
		};
		return exitHandler;
	}

	private void endGame() {
		print("END","GAME");
		finalAnimation().play();

	}

	private Timeline finalAnimation() {
		Timeline timeline = new Timeline();
		int count = 0;
		for (Node circle : gameCanvasPane.getChildren()) {

			System.out.println();
			print("gameCanvasWidth",gameCanvasWidth);
			print("circleWidth",circleWidth);
			print("circleRadius",circleRadius);

			int xOffset = 10;
			int yOffset = 184;

			MyPoint circlePoint = this.clickedCircleCoordinates.get(count);
			circlePoint.setX(circlePoint.getX() + xOffset);
			circlePoint.setY(circlePoint.getY() + yOffset);

			print("CirclePoint X", circlePoint.getX());
			print("CirclePoint Y", circlePoint.getY());

			MyPoint paneEndPoint = getBottomRightPointOfPane(root,gameCanvasPane);
			paneEndPoint.setX(paneEndPoint.getX() + xOffset);
			paneEndPoint.setY(paneEndPoint.getY() + yOffset);

			MyPoint paneStartPoint = getTopLeftPointOfPane(root,gameCanvasPane);
			paneStartPoint.setX(paneStartPoint.getX() + xOffset);
			paneStartPoint.setY(paneStartPoint.getY() + yOffset);

			print("paneStartPoint.getX()",paneStartPoint.getX());
			print("paneStartPoint.getY()",paneStartPoint.getY());
			print("paneEndPoint.getX()",paneEndPoint.getX());
			print("paneEndPoint.getY()",paneEndPoint.getY());

			System.out.println("*");

			// Pane dimensions
			int paneHeight = (int) (paneEndPoint.getY() - paneStartPoint.getY());
			int paneWidth = (int) (paneEndPoint.getX() - paneStartPoint.getX());

			int paneStartXCoord = (int) paneStartPoint.getX();
			int paneStartYCoord = (int) paneStartPoint.getY();

			int paneEndXCoord = (int) paneEndPoint.getX();
			int paneEndYCoord = (int) paneEndPoint.getY();

			// Circle 
			int circleX = (int) circlePoint.getX();
			int circleY = (int) circlePoint.getY();

			// Top zone
			int coordOfTopYZone = (int) (paneStartYCoord + circleRadius);
			int topRandYMin = (int) circleY - coordOfTopYZone;
			int topRandYMax = (int) (topRandYMin + (circleRadius / 2));

			// Right zone
			int coordOfRightXZone = (int) (paneEndXCoord - circleRadius);
			int rightRandXMin = (int)coordOfRightXZone - circleX;
			if(rightRandXMin <=0) {
				rightRandXMin = 1;
			}
			int rightRandXMax = (int) (rightRandXMin + (circleRadius / 2));

			// Bottom zone
			int coordOfBottomYZone = (int) (paneEndYCoord - circleRadius);
			int bottomRandYMin = (int) coordOfBottomYZone - circleY;
			if(bottomRandYMin <= 0) {
				bottomRandYMin = 1;
			}
			int bottomRandYMax = (int) (bottomRandYMin + (circleRadius / 2));

			// Left zone
			int coordOfLeftXZone = (int) (paneStartXCoord + circleRadius);
			int leftRandXMin = (int) circleX - coordOfLeftXZone;
			if (leftRandXMin <= 0) {
				leftRandXMin = 1;
			}
			int leftRandXMax = (int) (leftRandXMin + (circleRadius / 2));
			
			
			Random r = new Random();
			int randomX = 0;
			int randomY = 0;

			int xDice = r.nextInt(10)+1;
			if (xDice % 2 == 0) {
				// Left.
				randomX = r.nextInt(leftRandXMax - leftRandXMin) + leftRandXMin;
				print("LEFT","LEFT");
			} else {
				// Right.
				randomX = r.nextInt(rightRandXMax - rightRandXMin) + rightRandXMin;
				print("RIGHT","RIGHT");
			}
			
			randomY = r.nextInt(bottomRandYMax - bottomRandYMin) + 1;


			timeline.getKeyFrames().addAll(
					//					new KeyFrame(Duration.ZERO, // set start position at 0
					//							new KeyValue(circle.translateXProperty(), circlePoint.getX()),
					//							new KeyValue(circle.translateYProperty(), circlePoint.getY())),
					new KeyFrame(new Duration(1000), // set end position at 40s
							new KeyValue(circle.translateXProperty(), randomX),
							new KeyValue(circle.translateYProperty(), randomY)));

			count++;
		}
		// plays 40s of animation
		return timeline;
	}


	//	private Timeline finalAnimation() {
	//		Timeline timeline = new Timeline();
	//		int count = 0;
	//		for (Node circle : gameCanvasPane.getChildren()) {
	//
	//			System.out.println();
	//			print("gameCanvasWidth",gameCanvasWidth);
	//			print("circleWidth",circleWidth);
	//			print("circleRadius",circleRadius);
	//
	//			int xOffset = 10;
	//			int yOffset = 184;
	//
	//			MyPoint circlePoint = this.clickedCircleCoordinates.get(count);
	//			circlePoint.setX(circlePoint.getX() + xOffset);
	//			circlePoint.setY(circlePoint.getY() + yOffset);
	//
	//			print("CirclePoint X", circlePoint.getX());
	//			print("CirclePoint Y", circlePoint.getY());
	//
	//			MyPoint paneEndPoint = getBottomRightPointOfPane(root,gameCanvasPane);
	//			paneEndPoint.setX(paneEndPoint.getX() + xOffset);
	//			paneEndPoint.setY(paneEndPoint.getY() + yOffset);
	//
	//			MyPoint paneStartPoint = getTopLeftPointOfPane(root,gameCanvasPane);
	//			paneStartPoint.setX(paneStartPoint.getX() + xOffset);
	//			paneStartPoint.setY(paneStartPoint.getY() + yOffset);
	//
	//			print("paneStartPoint.getX()",paneStartPoint.getX());
	//			print("paneStartPoint.getY()",paneStartPoint.getY());
	//			print("paneEndPoint.getX()",paneEndPoint.getX());
	//			print("paneEndPoint.getY()",paneEndPoint.getY());
	//
	//			Random r = new Random();
	//			
	//			int randX = 0;
	//			int randXMax = 0;
	//			int randXMin = 1;
	//			int xDice = r.nextInt(10)+1;
	//			if (xDice % 2 == 0) {
	//				int distanceLeft = (int) (circlePoint.getX() - paneStartPoint.getX());
	//				randXMax = (int) (distanceLeft + circleRadius);
	//				int max = r.nextInt(randXMax - randXMin) + randXMin;
	//				randX = -max;
	//			} else {
	//				int distanceRight = (int) (paneEndPoint.getX() - circlePoint.getX());
	//				randXMax = (int) (distanceRight - circleRadius);
	//				randX = r.nextInt(randXMax - randXMin) + randXMin;
	//			}
	//			print("randXMax",randXMax);
	//			print("randX",randX);
	//			
	//			int randY = 0;
	//			int subtractOffsets = (int) (circleWidth + circleRadius);
	//			int distanceToBottom = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			int randYMin = 1;
	////			int randYMax = distanceToBottom - subtractOffsets;
	//			int randYMax = 0;
	////			int randYMax = (int) (distanceToBottom - circleRadius);
	//			if (distanceToBottom < subtractOffsets) {
	//				randYMax = distanceToBottom;
	//			} else {
	//				randYMax = (int) (distanceToBottom - subtractOffsets);
	//			}
	//			
	//			randY = r.nextInt(randYMax - randYMin) + randYMin;
	//			
	//			print("randYMax",randYMax);
	//			print("randY",randY);
	//
	//		
	//			//			int minYTransform = (int) ((paneEndPoint.getY() - circlePoint.getY()) - circleRadius);
	//			//			int maxYTransform = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			//			int ry = r.nextInt((maxYTransform - minYTransform)) + minYTransform;
	//
	//			//			int minYTransform = (int) ((paneEndPoint.getY() - circlePoint.getY()) - circleRadius);
	//			//			if (minYTransform <= 0) {
	//			//				minYTransform = 0;
	//			//			}
	//			//			int maxYTransform = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			//			int ry = r.nextInt((maxYTransform - minYTransform)) + minYTransform;
	//			//
	//			//			int minXTransform = (int) (circlePoint.getX() - circleWidth);
	//			//			print("minXTransform = ", minXTransform);
	//			//			if(minXTransform < 0){
	//			//				minXTransform = (int) (0 - circleRadius);
	//			//				print("ADJUSTED minXTransform = ", minXTransform);
	//			//			}
	//
	//			//			print("circlePoint.getX() - minXTransform = ", (circlePoint.getX() - minXTransform));
	//			//			if ((circlePoint.getX() - minXTransform) <= paneStartPoint.getX()){
	//			//				minXTransform += circleWidth;
	//			//				print("ADJUSTED minXTransform = ", minXTransform);
	//			//
	//			//			}
	//			//			int maxXTransform = (int) (circlePoint.getX() + circleWidth);
	//			//int maxXTransform = (int) (circlePoint.getX() + circleRadius);
	//
	//			//			print("maxXTransform = ",maxXTransform);
	//			//			print("circlePoint.getX() + maxXTransform = ", (circlePoint.getX() + maxXTransform));
	//			//			if ((circlePoint.getX() + maxXTransform) >= paneEndPoint.getX()){
	//			//				maxXTransform -= circleWidth;
	//			//				print("(ADJUSTED maxXTransform = ", maxXTransform);
	//			//
	//			//			}
	//
	//
	//			//			int rx = r.nextInt((maxXTransform - minXTransform)) + minXTransform;
	//			//			
	//			//			print("rx",rx);
	//			//			
	//			//			if(rx < 0){
	//			//				rx = (int) -circleRadius;
	//			//				print("ADJUSTED > 0 rx",rx);
	//			//			}
	//			//			
	//			//			print("rx + circlePoint.getX()",rx + circlePoint.getX());
	//			//			
	//			//			if((rx + circlePoint.getX()) > SCENE_WIDTH){
	//			////				rx = (int) (paneEndPoint.getX() - circleWidth);
	//			//				double diff = paneEndPoint.getX() - (circlePoint.getX() + circleWidth);
	//			//				double newrx = diff;
	//			//				print("newrx",newrx);
	//			//				rx = (int) newrx;
	//			//				print("ADJUSTED > scene rx",rx);
	//			//			}
	//			//			if((rx + circlePoint.getX()) > paneEndPoint.getX()){
	//			////				rx = (int) (paneEndPoint.getX() - circleWidth);
	//			//				double newrx = SCENE_WIDTH - 500;
	//			//				print("newrx",newrx);
	//			//				rx = (int) newrx;
	//			//				print("ADJUSTED > scene rx",rx);
	//			//			}
	//
	//
	//
	//
	//
	//
	//			//			if(rx > paneEndPoint.getX()){
	//			//				rx = (int) (paneEndPoint.getX() - 100);
	//			//			}
	//
	//			//print("rx",rx);
	//			//print("ry",ry);
	//
	//			timeline.getKeyFrames().addAll(
	//					//					new KeyFrame(Duration.ZERO, // set start position at 0
	//					//							new KeyValue(circle.translateXProperty(), circlePoint.getX()),
	//					//							new KeyValue(circle.translateYProperty(), circlePoint.getY())),
	//					new KeyFrame(new Duration(1000), // set end position at 40s
	//							new KeyValue(circle.translateXProperty(), randX),
	//							new KeyValue(circle.translateYProperty(), randY)));
	//
	//			count++;
	//		}
	//		// plays 40s of animation
	//		return timeline;
	//	}

	//	private Timeline finalAnimation() {
	//		Timeline timeline = new Timeline();
	//		int count = 0;
	//		for (Node circle : gameCanvasPane.getChildren()) {
	//			
	//			print("circleWidth",circleWidth);
	//			int xOffset = 10;
	//			int yOffset = 184;
	//
	//			MyPoint circlePoint = this.clickedCircleCoordinates.get(count);
	//			circlePoint.setX(circlePoint.getX() + xOffset);
	//			circlePoint.setY(circlePoint.getY() + yOffset);
	//
	//			print("CirclePoint X", circlePoint.getX());
	//			print("CirclePoint Y", circlePoint.getY());
	//
	//			MyPoint paneEndPoint = getBottomRightPointOfPane(root,gameCanvasPane);
	//			paneEndPoint.setX(paneEndPoint.getX() + xOffset);
	//			paneEndPoint.setY(paneEndPoint.getY() + yOffset);
	//
	//			MyPoint paneStartPoint = getTopLeftPointOfPane(root,gameCanvasPane);
	//			paneStartPoint.setX(paneStartPoint.getX() + xOffset);
	//			paneStartPoint.setY(paneStartPoint.getY() + yOffset);
	//
	//			print("paneEndPoint.getX()",paneEndPoint.getX());
	//			print("paneEndPoint.getY()",paneEndPoint.getY());
	//
	//			print("paneStartPoint.getX()",paneStartPoint.getX());
	//			print("paneStartPoint.getY()",paneStartPoint.getY());
	//
	//			Random r = new Random();
	//
	//			int minYTransform = (int) ((paneEndPoint.getY() - circlePoint.getY()) - circleRadius);
	//			int maxYTransform = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			int ry = r.nextInt((maxYTransform - minYTransform)) + minYTransform;
	//
	//			int minXTransform = (int) (circlePoint.getX() - circleWidth);
	//			print("minXTransform = ", minXTransform);
	//			if(minXTransform < 0){
	//				minXTransform = (int) (0 - circleRadius);
	//				print("ADJUSTED minXTransform = ", minXTransform);
	//			}
	//			
	////			print("circlePoint.getX() - minXTransform = ", (circlePoint.getX() - minXTransform));
	////			if ((circlePoint.getX() - minXTransform) <= paneStartPoint.getX()){
	////				minXTransform += circleWidth;
	////				print("ADJUSTED minXTransform = ", minXTransform);
	////
	////			}
	//			int maxXTransform = (int) (circlePoint.getX() + circleWidth);
	//			print("maxXTransform = ",maxXTransform);
	//			print("circlePoint.getX() + maxXTransform = ", (circlePoint.getX() + maxXTransform));
	//			if ((circlePoint.getX() + maxXTransform) >= paneEndPoint.getX()){
	//				maxXTransform -= circleWidth;
	//				print("(ADJUSTED maxXTransform = ", maxXTransform);
	//
	//			}
	//			int rx = r.nextInt((maxXTransform - minXTransform)) + minXTransform;
	//			if(rx < 0){
	//				rx = (int) -circleRadius;
	//			}
	//
	//			print("rx",rx);
	//			print("ry",ry);
	//
	//			timeline.getKeyFrames().addAll(
	//					//					new KeyFrame(Duration.ZERO, // set start position at 0
	//					//							new KeyValue(circle.translateXProperty(), circlePoint.getX()),
	//					//							new KeyValue(circle.translateYProperty(), circlePoint.getY())),
	//					new KeyFrame(new Duration(1000), // set end position at 40s
	//							new KeyValue(circle.translateXProperty(), rx),
	//							new KeyValue(circle.translateYProperty(), ry)));
	//
	//			count++;
	//		}
	//		// plays 40s of animation
	//		return timeline;
	//	}


	//	private Timeline finalAnimation() {
	//		Timeline timeline = new Timeline();
	//		int count = 0;
	//		for (Node circle : gameCanvasPane.getChildren()) {
	//			int xOffset = 10;
	//			int yOffset = 184;
	//
	//			MyPoint circlePoint = this.clickedCircleCoordinates.get(count);
	//			circlePoint.setX(circlePoint.getX() + xOffset);
	//			circlePoint.setY(circlePoint.getY() + yOffset);
	//
	//			print("CirclePoint X", circlePoint.getX());
	//			print("CirclePoint Y", circlePoint.getY());
	//
	//			MyPoint paneEndPoint = getBottomRightPointOfPane(root,gameCanvasPane);
	//			paneEndPoint.setX(paneEndPoint.getX() + xOffset);
	//			paneEndPoint.setY(paneEndPoint.getY() + yOffset);
	//
	//			MyPoint paneStartPoint = getTopLeftPointOfPane(root,gameCanvasPane);
	//			paneStartPoint.setX(paneStartPoint.getX() + xOffset);
	//			paneStartPoint.setY(paneStartPoint.getY() + yOffset);
	//
	//			print("paneEndPoint.getX()",paneEndPoint.getX());
	//			print("paneEndPoint.getY()",paneEndPoint.getY());
	//
	//			print("paneStartPoint.getX()",paneStartPoint.getX());
	//			print("paneStartPoint.getY()",paneStartPoint.getY());
	//
	//			Random r = new Random();
	//
	//			int minYTransform = (int) ((paneEndPoint.getY() - circlePoint.getY()) - circleRadius);
	//			int maxYTransform = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			int ry = r.nextInt((maxYTransform - minYTransform)) + minYTransform;
	//
	//			int minXTransform = (int) (circlePoint.getX() - circleWidth);
	//			print("minXTransform = ", minXTransform);
	//			print("circlePoint.getX() - minXTransform = ", (circlePoint.getX() - minXTransform));
	//			if ((circlePoint.getX() - minXTransform) <= paneStartPoint.getX()){
	//				minXTransform += circleWidth;
	//				print("ADJUSTED minXTransform = ", minXTransform);
	//
	//			}
	//			int maxXTransform = (int) (circlePoint.getX() + circleWidth);
	//			print("maxXTransform = ",maxXTransform);
	//			print("circlePoint.getX() + maxXTransform = ", (circlePoint.getX() + maxXTransform));
	//			if ((circlePoint.getX() + maxXTransform) >= paneEndPoint.getX()){
	//				maxXTransform -= circleWidth;
	//				print("(ADJUSTED maxXTransform = ", maxXTransform);
	//
	//			}
	//			int rx = r.nextInt((maxXTransform - minXTransform)) + minXTransform;
	//
	//			print("rx",rx);
	//			print("ry",ry);
	//
	//			timeline.getKeyFrames().addAll(
	//					//					new KeyFrame(Duration.ZERO, // set start position at 0
	//					//							new KeyValue(circle.translateXProperty(), circlePoint.getX()),
	//					//							new KeyValue(circle.translateYProperty(), circlePoint.getY())),
	//					new KeyFrame(new Duration(1000), // set end position at 40s
	//							new KeyValue(circle.translateXProperty(), rx),
	//							new KeyValue(circle.translateYProperty(), ry)));
	//
	//			count++;
	//		}
	//		// plays 40s of animation
	//		return timeline;
	//	}

	//	private Timeline finalAnimation() {
	//		Timeline timeline = new Timeline();
	//		int count = 0;
	//		for (Node circle : gameCanvasPane.getChildren()) {
	//			MyPoint circlePoint = this.clickedCircleCoordinates.get(count);
	//			
	//			print("CirclePoint X", circlePoint.getX());
	//			print("CirclePoint Y", circlePoint.getY());
	//			
	//			MyPoint paneEndPoint = getBottomRightPointOfPane(root,gameCanvasPane);
	//			MyPoint paneStartPoint = getTopLeftPointOfPane(root,gameCanvasPane);
	//
	//			print("paneEndPoint.getX()",paneEndPoint.getX());
	//			print("paneEndPoint.getY()",paneEndPoint.getY());
	//			
	//			print("paneStartPoint.getX()",paneStartPoint.getX());
	//			print("paneStartPoint.getY()",paneStartPoint.getY());
	//
	//			double currentY = circlePoint.getY();
	//			double endY = paneEndPoint.getY();
	//			double diffY = endY - currentY;
	//			
	//			double currentX = circlePoint.getX();
	//			double endX = paneEndPoint.getX();
	//			double diffX = endX - currentX;
	//			
	//			print("diffX",diffX);
	//			print("diffY",diffY);
	//			
	//			Random r = new Random();
	//			
	//			
	//			int minYTransform = (int) ((paneEndPoint.getY() - circlePoint.getY()) - circleRadius);
	//			int maxYTransform = (int) (paneEndPoint.getY() - circlePoint.getY());
	//			int ry = r.nextInt((maxYTransform - minYTransform)) + minYTransform;
	//			
	//			int minXTransform = (int) (circlePoint.getX() - circleWidth);
	//			print("minXTransform = ", minXTransform);
	//			print("circlePoint.getX() - minXTransform = ", (circlePoint.getX() - minXTransform));
	//			if ((circlePoint.getX() - minXTransform) <= paneStartPoint.getX()){
	//				minXTransform += circleWidth;
	//				print("ADJUSTED minXTransform = ", minXTransform);
	//
	//			}
	//			int maxXTransform = (int) (circlePoint.getX() + circleWidth);
	//			print("maxXTransform = ",maxXTransform);
	//			print("circlePoint.getX() + maxXTransform = ", (circlePoint.getX() + maxXTransform));
	//			if ((circlePoint.getX() + maxXTransform) >= paneEndPoint.getX()){
	//				maxXTransform -= circleWidth;
	//				print("(ADJUSTED maxXTransform = ", maxXTransform);
	//
	//			}
	//			int rx = r.nextInt((maxXTransform - minXTransform)) + minXTransform;
	//			
	////			int rx2 = rx + 10;
	////			int ry2 = ry + 182;
	//			
	//	
	//			print("rx",rx);
	//			print("ry",ry);
	//			
	//			timeline.getKeyFrames().addAll(
	////					new KeyFrame(Duration.ZERO, // set start position at 0
	////							new KeyValue(circle.translateXProperty(), circlePoint.getX()),
	////							new KeyValue(circle.translateYProperty(), circlePoint.getY())),
	//							new KeyFrame(new Duration(1000), // set end position at 40s
	//									new KeyValue(circle.translateXProperty(), rx),
	//									new KeyValue(circle.translateYProperty(), ry)));
	//			
	//			count++;
	//		}
	//		// plays 40s of animation
	//		return timeline;
	//	}

	private MyPoint getTopLeftPointOfPane(Pane parent, Pane child) {
		// Find the top left corner coordinates of the 
		// child pane inside the parent.
		MyPoint p = new MyPoint();
		int childIndex = parent.getChildren().indexOf(child);
		double minX = root.getChildren().get(childIndex).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(childIndex).getBoundsInParent().getMinY();
		p.setX(minX);
		p.setY(minY);
		return p;
	}

	private MyPoint getBottomRightPointOfPane(Pane parent, Pane child) {
		// Find the top left corner coordinates of the 
		// child pane inside the parent.
		MyPoint p = new MyPoint();
		int childIndex = parent.getChildren().indexOf(child);
		double maxX = root.getChildren().get(childIndex).getBoundsInParent().getMaxX();
		double maxY = root.getChildren().get(childIndex).getBoundsInParent().getMaxY();
		p.setX(maxX);
		p.setY(maxY);
		return p;
	}

	private MyPoint getPointInsideOfPane(MyPoint clickedPointInPane, MyPoint topLeftPointOfPane) {
		// Adjust the clicked coordinate in the scene
		// to the actual coordinate in the game canvas.
		MyPoint p = new MyPoint();
		p.setX(clickedPointInPane.getX() - topLeftPointOfPane.getX());
		p.setY(clickedPointInPane.getY() - topLeftPointOfPane.getY());
		return p;
	}

	private MyPoint findCircle(MyPoint clickedInScene) {
		// Get topleft coord of game canvas.
		MyPoint gameCanvasTopLeftCoords = getTopLeftPointOfPane(root,gameCanvasPane);
		// Convert the scene coordinate to a game canvas coordinate.
		MyPoint gameCanvasClickedPoint = getPointInsideOfPane(clickedInScene,gameCanvasTopLeftCoords);
		// Get the index position the shape occupies on screen.
		// eg. 1 circle across, 2 circles down.
		// Note: Positions begin at zero.
		int xPos = getPositionOnAxis(gameCanvasClickedPoint.getX());
		int yPos = getPositionOnAxis(gameCanvasClickedPoint.getY());
		// Get the index position of the shape.
		int position = getPositionInGrid(xPos,yPos);
		// Put the position index and coordinates of the shape into the map.
		MyPoint p = getCoordinates(xPos,yPos);
		p.setPosition(position);
		return p;

	}

	private void addClickedCircle(MyPoint clickedInScene) {
		MyPoint p = findCircle(clickedInScene);
		clickedCircleCoordinates.put(p.getPosition(),p);

		print("Added Position:: ",p.toString());
		print("circleCoordinates.size", clickedCircleCoordinates.size());
	}

	private MyPoint getCoordinates(int xAxisPosition, int yAxisPosition) {
		MyPoint p = new MyPoint();
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		p.setX(minX + (xAxisPosition * circleWidth));
		p.setY(minY + (yAxisPosition * circleWidth));
		return p;
	}

	private int findNodeIndex(MyPoint clickedInScene) {

		return 0;
	}

	private int getPositionOnAxis(double clickedCoord) {
		// Divide the clicked coordinate by the circle's width
		// to find the position of the circle (horizontal or vertical).
		// Note: Circle width is the same as equal height.
		int pos = (int) (clickedCoord / circleWidth);
		return pos;
	}

	public int getPositionInGrid(int xAxisPosition, int yAxisPosition) {
		// xPos and yPos range begin from 0.
		// Convert xPos and yPos to position numbers
		// by adding 1.
		int convertToPositionNumberX = xAxisPosition + 1;
		int convertToPositionNumberY = yAxisPosition + 1;
		int positionNumber;
		int balanceOfRow = numOfCirclesAcross - convertToPositionNumberX;
		print("Balance of row", balanceOfRow);
		positionNumber = (numOfCirclesAcross * convertToPositionNumberY) - balanceOfRow;
		// Convert the position back to a range beginning with 0
		// to ensure it's correct position in collections.
		int indexPosition = positionNumber - 1;
		return indexPosition;
	}

	private void initialiseCircleCollectionDimensions() {
		if (numOfCirclesAcross == 1){
			circleWidth = gameCanvasWidth / 3;
		} else {
			circleWidth = gameCanvasWidth / numOfCirclesAcross;
		}
		circleRadius = circleWidth / 2;
		numOfCirclesDown = (int) (gameCanvasHeight / circleWidth);
		totalNumOfCircles = numOfCirclesAcross * numOfCirclesDown;
	}

	private void getLocationOfGameCanvasInParent() {
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		double maxX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxX();
		double maxY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxY();
	}

	private EventHandler<MouseEvent> makeBorderPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("BorderPane " + event.getSceneX());
				System.out.println("BorderPane " + event.getSceneY());
			}
		};
		return clickHandler;
	}

	private EventHandler<MouseEvent> makeFlowPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("FlowPane " + event.getSceneX());
				System.out.println("FlowPane " + event.getSceneY());
				int iHUDPane = root.getChildren().indexOf(HUDPane);
				System.out.println("iHUDPane: " + iHUDPane);
				int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
				System.out.println("igameCanvasPane: " + igameCanvasPane);
				System.out.println("BOUNDS: " + root.getChildren().get(igameCanvasPane).getBoundsInParent());
			}
		};
		return clickHandler;
	}

	private void print(String tag, Object value) {
		System.out.println(tag + " " + value);
	}

	private void testing() {
		print("SCENE_WIDTH",SCENE_WIDTH);
		print("SCENE_HEIGHT",SCENE_HEIGHT);
		print("SCENE_INSET_TOP",SCENE_INSET_TOP);
		print("SCENE_INSET_RIGHT",SCENE_INSET_RIGHT);
		print("SCENE_INSET_BOTTOM",SCENE_INSET_BOTTOM);
		print("SCENE_INSET_LEFT",SCENE_INSET_LEFT);
		print("HUD_WIDTH_PERCENT",HUD_WIDTH_PERCENT);
		print("HUD_HEIGHT_PERCENT",HUD_HEIGHT_PERCENT);
		print("GAMECANVAS_WIDTH_PERCENT",GAMECANVAS_WIDTH_PERCENT);
		print("GAMECANVAS_HEIGHT_PERCENT",GAMECANVAS_HEIGHT_PERCENT);
		print("adjustedSceneWidth",adjustedSceneWidth);
		print("adjustedSceneHeight",adjustedSceneHeight);
		print("HUDWidth",HUDWidth);
		print("HUDHeight",HUDHeight);
		print("gameCanvasWidth",gameCanvasWidth);
		print("gameCanvasHeight",gameCanvasHeight);
		print("circleWidth",circleWidth);
		print("circleRadius",circleRadius);
		print("numOfCirclesAcross",numOfCirclesAcross);
		print("numOfCirclesDown",numOfCirclesDown);
		print("totalNumOfCircles",totalNumOfCircles);

		root.addEventHandler(MouseEvent.MOUSE_MOVED, makeBorderPaneMovedHandler());

		gameCanvasPane.addEventHandler(MouseEvent.MOUSE_MOVED, makeFlowPaneMovedHandler());


	}


}
